import { RouteItem } from '@/api/model/permissionModel';
import { RouteMeta } from '@/types/interface';
import { BLANK_LAYOUT, EXCEPTION_COMPONENT, IFRAME, LAYOUT } from '@/utils/route/constant';

// vite 3+ support dynamic import from node_modules
const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();

LayoutMap.set('LAYOUT', LAYOUT);
LayoutMap.set('BLANK', BLANK_LAYOUT);
LayoutMap.set('IFRAME', IFRAME);

let dynamicViewsModules: Record<string, () => Promise<Recordable>>;

function dynamicImport(component: string) {
  dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../pages/**/*.vue');
  const keys = Object.keys(dynamicViewsModules);
  const matchKeys = keys.filter((key) => {
    const k = key.replace('../../pages', '');
    const startFlag = component.startsWith('/');
    const endFlag = component.endsWith('.vue') || component.endsWith('.tsx');
    const startIndex = startFlag ? 0 : 1;
    const lastIndex = endFlag ? k.length : k.lastIndexOf('.');
    return k.substring(startIndex, lastIndex) === component;
  });
  if (matchKeys?.length === 1) {
    const matchKey = matchKeys[0];
    return dynamicViewsModules[matchKey];
  }
  if (matchKeys?.length > 1) {
    throw new Error(
      'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure',
    );
  } else {
    console.warn(`Can't find ${component} in pages folder`);
  }
  return EXCEPTION_COMPONENT;
}

export function filterAsyncRouter<T = RouteItem>(routeList: any[]): T[] {
  const routers = routeList.filter((v) => v.display === 1);

  routers.forEach((item) => {
    const langs = item.langs ? JSON.parse(item.langs) : {};
    item.path = item.componentRoute || '/';
    item.meta = {
      title: {
        zh_CN: item.name,
        ...langs,
      },
      icon: item.icon,
      mainBg: item.mainBg || false,
    } as RouteMeta;
    item.name = item.componentName || item.name;
    // if (item.meta.icon) item.meta.icon = await getMenuIcon(item.meta.icon);
    if (item.componentPath === 'Layout') {
      item.component = LAYOUT;
    } else if (item.componentPath === 'Blank') {
      item.component = BLANK_LAYOUT;
    } else {
      item.component = dynamicImport(item.componentPath);
    }
    if (item.children && item.children.length) {
      item.children = filterAsyncRouter(item.children.filter((v: any) => v.type !== 2));
    }
  });

  return routers as unknown as T[];
}

export const flattenTree = (tree: any[]) => {
  return tree.reduce((acc, node) => {
    acc.push(node);
    if (node.children.length) {
      acc.push(...flattenTree(node.children));
    }

    return acc;
  }, []);
};
